home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_temp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  14.9 KB  |  872 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_temp.c    7.6 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_temp.h"
  13. #include "ex_vis.h"
  14. #include "ex_tty.h"
  15.  
  16. /*
  17.  * Editor temporary file routines.
  18.  * Very similar to those of ed, except uses 2 input buffers.
  19.  */
  20. #define    READ    0
  21. #define    WRITE    1
  22.  
  23. #ifndef vms
  24. #define    EPOSITION    7
  25. #else
  26. #define    EPOSITION    13
  27. #endif
  28.  
  29. char    tfname[40];
  30. char    rfname[40];
  31. int    havetmp;
  32. short    tfile = -1;
  33. short    rfile = -1;
  34.  
  35. fileinit()
  36. {
  37.     register char *p;
  38.     register int i, j;
  39.     struct stat stbuf;
  40.  
  41.     if (tline == INCRMT * (HBLKS+2))
  42.         return;
  43.     cleanup(0);
  44.     if (tfile >= 0)
  45.         close(tfile);
  46.     tline = INCRMT * (HBLKS+2);
  47.     blocks[0] = HBLKS;
  48.     blocks[1] = HBLKS+1;
  49.     blocks[2] = -1;
  50.     dirtcnt = 0;
  51.     iblock = -1;
  52.     iblock2 = -1;
  53.     oblock = -1;
  54.     CP(tfname, svalue(DIRECTORY));
  55. #ifndef vms
  56.     if (stat(tfname, &stbuf))
  57. #else
  58.     goto vms_no_check_dir;
  59. #endif
  60.     {
  61. dumbness:
  62.         if (setexit() == 0)
  63.             filioerr(tfname);
  64.         else
  65.             putNFL();
  66.         cleanup(1);
  67.         ex_exit(1);
  68.     }
  69. #ifndef    vms
  70.     if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
  71.         errno = ENOTDIR;
  72.         goto dumbness;
  73.     }
  74. #else
  75. vms_no_check_dir:
  76. #endif
  77.     ichanged = 0;
  78.     ichang2 = 0;
  79. #ifndef    vms
  80.     ignore(strcat(tfname, "/ExXXXXX"));
  81. #else
  82.     ignore(strcat(tfname, "ExXXXXX"));
  83. #endif
  84.     for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
  85.         *--p = j % 10 | '0';
  86. #ifdef vms
  87.     ignore(strcat(tfname, ".txt.1"));
  88.     unlink(tfname);
  89. #endif
  90.     tfile = creat(tfname, 0600);
  91.     if (tfile < 0)
  92.         goto dumbness;
  93. #ifdef VMUNIX
  94.     {
  95.         extern stilinc;        /* see below */
  96.         stilinc = 0;
  97.     }
  98. #endif
  99.     havetmp = 1;
  100.     if (tfile >= 0)
  101.         close(tfile);
  102.     tfile = open(tfname, 2);
  103.     if (tfile < 0)
  104.         goto dumbness;
  105. #ifdef UNIX_SBRK
  106. /*     brk((char *)fendcore); */
  107. #endif
  108. }
  109.  
  110. cleanup(all)
  111.     bool all;
  112. {
  113.     if (all) {
  114.         putpad(TE);
  115.         flush();
  116.     }
  117.     if (havetmp) {
  118.         if (tfile >= 0)
  119.             close(tfile);
  120.         unlink(tfname);
  121.     }
  122.     havetmp = 0;
  123.     if (all && rfile >= 0) {
  124.         if (rfile >= 0)
  125.             close(rfile);
  126.         unlink(rfname);
  127.         rfile = -1;
  128.     }
  129. }
  130.  
  131. getline(tl)
  132.     line tl;
  133. {
  134.     register char *bp, *lp;
  135.     register int nl;
  136.  
  137.     lp = linebuf;
  138.     bp = getblock(tl, READ);
  139.     nl = nleft;
  140.     tl &= ~OFFMSK;
  141.     while (*lp++ = *bp++)
  142.         if (--nl == 0) {
  143.             bp = getblock(tl += INCRMT, READ);
  144.             nl = nleft;
  145.         }
  146. }
  147.  
  148. putline()
  149. {
  150.     register char *bp, *lp;
  151.     register int nl;
  152.     line tl;
  153.  
  154.     dirtcnt++;
  155.     lp = linebuf;
  156.     change();
  157.     tl = tline;
  158.     bp = getblock(tl, WRITE);
  159.     nl = nleft;
  160.     tl &= ~OFFMSK;
  161.     while (*bp = *lp++) {
  162.         if (*bp++ == '\n') {
  163.             *--bp = 0;
  164.             linebp = lp;
  165.             break;
  166.         }
  167.         if (--nl == 0) {
  168.             bp = getblock(tl += INCRMT, WRITE);
  169.             nl = nleft;
  170.         }
  171.     }
  172.     tl = tline;
  173.     tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
  174.     return (tl);
  175. }
  176.  
  177. int    read();
  178. int    write();
  179.  
  180. char *
  181. getblock(atl, iof)
  182.     line atl;
  183.     int iof;
  184. {
  185.     register int bno, off;
  186. #ifdef CRYPT
  187.         register char *p1, *p2;
  188.         register int n;
  189. #endif
  190.     
  191.     bno = (atl >> OFFBTS) & BLKMSK;
  192.     off = (atl << SHFT) & LBTMSK;
  193.     if (bno >= NMBLKS)
  194.         error(" Tmp file too large");
  195.     nleft = BUFSIZ - off;
  196.     if (bno == iblock) {
  197.         ichanged |= iof;
  198.         hitin2 = 0;
  199.         return (ibuff + off);
  200.     }
  201.     if (bno == iblock2) {
  202.         ichang2 |= iof;
  203.         hitin2 = 1;
  204.         return (ibuff2 + off);
  205.     }
  206.     if (bno == oblock)
  207.         return (obuff + off);
  208.     if (iof == READ) {
  209.         if (hitin2 == 0) {
  210.             if (ichang2) {
  211. #ifdef CRYPT
  212.                 if(xtflag)
  213.                     crblock(tperm, ibuff2, CRSIZE, (long)0);
  214. #endif
  215.                 blkio(iblock2, ibuff2, write);
  216.             }
  217.             ichang2 = 0;
  218.             iblock2 = bno;
  219.             blkio(bno, ibuff2, read);
  220. #ifdef CRYPT
  221.             if(xtflag)
  222.                 crblock(tperm, ibuff2, CRSIZE, (long)0);
  223. #endif
  224.             hitin2 = 1;
  225.             return (ibuff2 + off);
  226.         }
  227.         hitin2 = 0;
  228.         if (ichanged) {
  229. #ifdef CRYPT
  230.             if(xtflag)
  231.                 crblock(tperm, ibuff, CRSIZE, (long)0);
  232. #endif
  233.             blkio(iblock, ibuff, write);
  234.         }
  235.         ichanged = 0;
  236.         iblock = bno;
  237.         blkio(bno, ibuff, read);
  238. #ifdef CRYPT
  239.         if(xtflag)
  240.             crblock(tperm, ibuff, CRSIZE, (long)0);
  241. #endif
  242.         return (ibuff + off);
  243.     }
  244.     if (oblock >= 0) {
  245. #ifdef CRYPT
  246.         if(xtflag) {
  247.             /*
  248.              * Encrypt block before writing, so some devious
  249.              * person can't look at temp file while editing.
  250.              */
  251.             p1 = obuff;
  252.             p2 = crbuf;
  253.             n = CRSIZE;
  254.             while(n--)
  255.                 *p2++ = *p1++;
  256.             crblock(tperm, crbuf, CRSIZE, (long)0);
  257.             blkio(oblock, crbuf, write);
  258.         } else
  259. #endif
  260.             blkio(oblock, obuff, write);
  261.     }
  262.     oblock = bno;
  263.     return (obuff + off);
  264. }
  265.  
  266. #ifdef    VMUNIX
  267. #ifdef    vms
  268. #define    INCORB    32
  269. #else
  270. #define    INCORB    64
  271. #endif
  272. char    incorb[INCORB+1][BUFSIZ];
  273. #define    pagrnd(a)    ((char *)(((int)a)&~(BUFSIZ-1)))
  274. int    stilinc;    /* up to here not written yet */
  275. #endif
  276.  
  277. blkio(b, buf, iofcn)
  278.     short b;
  279.     char *buf;
  280.     int (*iofcn)();
  281. {
  282.  
  283. #ifdef VMUNIX
  284.     if (b < INCORB) {
  285.         if (iofcn == read) {
  286.             bcopy(pagrnd(incorb[b+1]), buf, BUFSIZ);
  287.             return;
  288.         }
  289.         bcopy(buf, pagrnd(incorb[b+1]), BUFSIZ);
  290.         if (laste) {
  291.             if (b >= stilinc)
  292.                 stilinc = b + 1;
  293.             return;
  294.         }
  295.     } else if (stilinc)
  296.         tflush();
  297. #endif
  298.     lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
  299.     if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
  300.         filioerr(tfname);
  301. }
  302.  
  303. #ifdef VMUNIX
  304. tlaste()
  305. {
  306.  
  307.     if (stilinc)
  308.         dirtcnt = 0;
  309. }
  310.  
  311. tflush()
  312. {
  313.     int i = stilinc;
  314.     
  315.     stilinc = 0;
  316.     lseek(tfile, (long) 0, 0);
  317.     if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
  318.         filioerr(tfname);
  319. }
  320. #endif
  321.  
  322. /*
  323.  * Synchronize the state of the temporary file in case
  324.  * a crash occurs.
  325.  */
  326. synctmp()
  327. {
  328.     register int cnt;
  329.     register line *a;
  330.     register short *bp;
  331.  
  332. #ifdef VMUNIX
  333.     if (stilinc)
  334.         return;
  335. #endif
  336.     if (dol == zero)
  337.         return;
  338.     if (ichanged)
  339.         blkio(iblock, ibuff, write);
  340.     ichanged = 0;
  341.     if (ichang2)
  342.         blkio(iblock2, ibuff2, write);
  343.     ichang2 = 0;
  344.     if (oblock != -1)
  345.         blkio(oblock, obuff, write);
  346.     time(&H.Time);
  347.     uid = getuid();
  348.     *zero = (line) H.Time;
  349.     for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
  350.         if (*bp < 0) {
  351.             tline = (tline + OFFMSK) &~ OFFMSK;
  352.             *bp = ((tline >> OFFBTS) & BLKMSK);
  353.             if (*bp > NMBLKS)
  354.                 error(" Tmp file too large");
  355.             tline += INCRMT;
  356.             oblock = *bp + 1;
  357.             bp[1] = -1;
  358.         }
  359.         lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
  360.         cnt = ((dol - a) + 2) * sizeof (line);
  361.         if (cnt > BUFSIZ)
  362.             cnt = BUFSIZ;
  363.         if (write(tfile, (char *) a, cnt) != cnt) {
  364. oops:
  365.             *zero = 0;
  366.             filioerr(tfname);
  367.         }
  368.         *zero = 0;
  369.     }
  370.     flines = lineDOL();
  371.     lseek(tfile, 0l, 0);
  372.     if (write(tfile, (char *) &H, sizeof H) != sizeof H)
  373.         goto oops;
  374. #ifdef notdef
  375.     /*
  376.      * This will insure that exrecover gets as much
  377.      * back after a crash as is absolutely possible,
  378.      * but can result in pregnant pauses between commands
  379.      * when the TSYNC call is made, so...
  380.      */
  381. #ifndef vms
  382.     (void) fsync(tfile);
  383. #endif
  384. #endif
  385. }
  386.  
  387. TSYNC()
  388. {
  389.  
  390.     if (dirtcnt > MAXDIRT) {    /* mjm: 12 --> MAXDIRT */
  391. #ifdef VMUNIX
  392.         if (stilinc)
  393.             tflush();
  394. #endif
  395.         dirtcnt = 0;
  396.         synctmp();
  397.     }
  398. }
  399.  
  400. /*
  401.  * Named buffer routines.
  402.  * These are implemented differently than the main buffer.
  403.  * Each named buffer has a chain of blocks in the register file.
  404.  * Each block contains roughly 508 chars of text,
  405.  * and a previous and next block number.  We also have information
  406.  * about which blocks came from deletes of multiple partial lines,
  407.  * e.g. deleting a sentence or a LISP object.
  408.  *
  409.  * We maintain a free map for the temp file.  To free the blocks
  410.  * in a register we must read the blocks to find how they are chained
  411.  * together.
  412.  *
  413.  * BUG:        The default savind of deleted lines in numbered
  414.  *        buffers may be rather inefficient; it hasn't been profiled.
  415.  */
  416. struct    strreg {
  417.     short    rg_flags;
  418.     short    rg_nleft;
  419.     short    rg_first;
  420.     short    rg_last;
  421. } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
  422.  
  423. struct    rbuf {
  424.     short    rb_prev;
  425.     short    rb_next;
  426.     char    rb_text[BUFSIZ - 2 * sizeof (short)];
  427. } *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
  428. #ifdef VMUNIX
  429. short    rused[256];
  430. #else
  431. short    rused[32];
  432. #endif
  433. short    rnleft;
  434. short    rblock;
  435. short    rnext;
  436. char    *rbufcp;
  437.  
  438. regio(b, iofcn)
  439.     short b;
  440.     int (*iofcn)();
  441. {
  442.  
  443.     if (rfile == -1) {
  444.         CP(rfname, tfname);
  445.         *(strend(rfname) - EPOSITION) = 'R';
  446.         rfile = creat(rfname, 0600);
  447.         if (rfile < 0)
  448. oops:
  449.             filioerr(rfname);
  450.         else
  451.             close(rfile);
  452.         rfile = open(rfname, 2);
  453.         if (rfile < 0)
  454.             goto oops;
  455.     }
  456.     lseek(rfile, (long) b * BUFSIZ, 0);
  457.     if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
  458.         goto oops;
  459.     rblock = b;
  460. }
  461.  
  462. REGblk()
  463. {
  464.     register int i, j, m;
  465.  
  466.     for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
  467.         m = (rused[i] ^ 0177777) & 0177777;
  468.         if (i == 0)
  469.             m &= ~1;
  470.         if (m != 0) {
  471.             j = 0;
  472.             while ((m & 1) == 0)
  473.                 j++, m >>= 1;
  474.             rused[i] |= (1 << j);
  475. #ifdef RDEBUG
  476.             ex_printf("allocating block %d\n", i * 16 + j);
  477. #endif
  478.             return (i * 16 + j);
  479.         }
  480.     }
  481.     error("Out of register space (ugh)");
  482.     /*NOTREACHED*/
  483. }
  484.  
  485. struct    strreg *
  486. mapreg(c)
  487.     register int c;
  488. {
  489.  
  490.     if (isupper(c))
  491.         c = tolower(c);
  492.     return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
  493. }
  494.  
  495. int    shread();
  496.  
  497. KILLreg(c)
  498.     register int c;
  499. {
  500.     register struct strreg *sp;
  501.  
  502.     rbuf = &KILLrbuf;
  503.     sp = mapreg(c);
  504.     rblock = sp->rg_first;
  505.     sp->rg_first = sp->rg_last = 0;
  506.     sp->rg_flags = sp->rg_nleft = 0;
  507.     while (rblock != 0) {
  508. #ifdef RDEBUG
  509.         ex_printf("freeing block %d\n", rblock);
  510. #endif
  511.         rused[rblock / 16] &= ~(1 << (rblock % 16));
  512.         regio(rblock, shread);
  513.         rblock = rbuf->rb_next;
  514.     }
  515. }
  516.  
  517. /*VARARGS*/
  518. shread()
  519. {
  520.     struct front { short a; short b; };
  521.  
  522.     if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
  523.         return (sizeof (struct rbuf));
  524.     return (0);
  525. }
  526.  
  527. int    getREG();
  528.  
  529. putreg(c)
  530.     char c;
  531. {
  532.     register line *odot = dot;
  533.     register line *odol = dol;
  534.     register int cnt;
  535.  
  536.     deletenone();
  537.     appendnone();
  538.     rbuf = &putrbuf;
  539.     rnleft = 0;
  540.     rblock = 0;
  541.     rnext = mapreg(c)->rg_first;
  542.     if (rnext == 0) {
  543.         if (inopen) {
  544.             splitw++;
  545.             vclean();
  546.             vgoto(WECHO, 0);
  547.         }
  548.         vreg = -1;
  549.         error("Nothing in register %c", c);
  550.     }
  551.     if (inopen && partreg(c)) {
  552.         if (!FIXUNDO) {
  553.             splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
  554.             error("Can't put partial line inside macro");
  555.         }
  556.         squish();
  557.         addr1 = addr2 = dol;
  558.     }
  559.     cnt = append(getREG, addr2);
  560.     if (inopen && partreg(c)) {
  561.         unddol = dol;
  562.         dol = odol;
  563.         dot = odot;
  564.         pragged(0);
  565.     }
  566.     killcnt(cnt);
  567.     notecnt = cnt;
  568. }
  569.  
  570. partreg(c)
  571.     char c;
  572. {
  573.  
  574.     return (mapreg(c)->rg_flags);
  575. }
  576.  
  577. notpart(c)
  578.     register int c;
  579. {
  580.  
  581.     if (c)
  582.         mapreg(c)->rg_flags = 0;
  583. }
  584.  
  585. getREG()
  586. {
  587.     register char *lp = linebuf;
  588.     register int c;
  589.  
  590.     for (;;) {
  591.         if (rnleft == 0) {
  592.             if (rnext == 0)
  593.                 return (EOF);
  594.             regio(rnext, read);
  595.             rnext = rbuf->rb_next;
  596.             rbufcp = rbuf->rb_text;
  597.             rnleft = sizeof rbuf->rb_text;
  598.         }
  599.         c = *rbufcp;
  600.         if (c == 0)
  601.             return (EOF);
  602.         rbufcp++, --rnleft;
  603.         if (c == '\n') {
  604.             *lp++ = 0;
  605.             return (0);
  606.         }
  607.         *lp++ = c;
  608.     }
  609. }
  610.  
  611. YANKreg(c)
  612.     register int c;
  613. {
  614.     register line *addr;
  615.     register struct strreg *sp;
  616.     char savelb[LBSIZE];
  617.  
  618.     if (isdigit(c))
  619.         kshift();
  620.     if (islower(c))
  621.         KILLreg(c);
  622.     strp = sp = mapreg(c);
  623.     sp->rg_flags = inopen && cursor && wcursor;
  624.     rbuf = &YANKrbuf;
  625.     if (sp->rg_last) {
  626.         regio(sp->rg_last, read);
  627.         rnleft = sp->rg_nleft;
  628.         rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
  629.     } else {
  630.         rblock = 0;
  631.         rnleft = 0;
  632.     }
  633.     CP(savelb,linebuf);
  634.     for (addr = addr1; addr <= addr2; addr++) {
  635.         getline(*addr);
  636.         if (sp->rg_flags) {
  637.             if (addr == addr2)
  638.                 *wcursor = 0;
  639.             if (addr == addr1)
  640.                 strcpy(linebuf, cursor);
  641.         }
  642.         YANKline();
  643.     }
  644.     rbflush();
  645.     killed();
  646.     CP(linebuf,savelb);
  647. }
  648.  
  649. kshift()
  650. {
  651.     register int i;
  652.  
  653.     KILLreg('9');
  654.     for (i = '8'; i >= '0'; i--)
  655.         copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
  656. }
  657.  
  658. YANKline()
  659. {
  660.     register char *lp = linebuf;
  661.     register struct rbuf *rp = rbuf;
  662.     register int c;
  663.  
  664.     do {
  665.         c = *lp++;
  666.         if (c == 0)
  667.             c = '\n';
  668.         if (rnleft == 0) {
  669.             rp->rb_next = REGblk();
  670.             rbflush();
  671.             rblock = rp->rb_next;
  672.             rp->rb_next = 0;
  673.             rp->rb_prev = rblock;
  674.             rnleft = sizeof rp->rb_text;
  675.             rbufcp = rp->rb_text;
  676.         }
  677.         *rbufcp++ = c;
  678.         --rnleft;
  679.     } while (c != '\n');
  680.     if (rnleft)
  681.         *rbufcp = 0;
  682. }
  683.  
  684. rbflush()
  685. {
  686.     register struct strreg *sp = strp;
  687.  
  688.     if (rblock == 0)
  689.         return;
  690.     regio(rblock, write);
  691.     if (sp->rg_first == 0)
  692.         sp->rg_first = rblock;
  693.     sp->rg_last = rblock;
  694.     sp->rg_nleft = rnleft;
  695. }
  696.  
  697. /* Register c to char buffer buf of size buflen */
  698. regbuf(c, buf, buflen)
  699. char c;
  700. char *buf;
  701. int buflen;
  702. {
  703.     register char *p, *lp;
  704.  
  705.     rbuf = ®rbuf;
  706.     rnleft = 0;
  707.     rblock = 0;
  708.     rnext = mapreg(c)->rg_first;
  709.     if (rnext==0) {
  710.         *buf = 0;
  711.         error("Nothing in register %c",c);
  712.     }
  713.     p = buf;
  714.     while (getREG()==0) {
  715.         for (lp=linebuf; *lp;) {
  716.             if (p >= &buf[buflen])
  717.                 error("Register too long@to fit in memory");
  718.             *p++ = *lp++;
  719.         }
  720.         *p++ = '\n';
  721.     }
  722.     if (partreg(c)) p--;
  723.     *p = '\0';
  724.     getDOT();
  725. }
  726.  
  727. /*
  728.  * Encryption routines.  These are essentially unmodified from ed.
  729.  */
  730.  
  731. #ifdef CRYPT
  732. /*
  733.  * crblock: encrypt/decrypt a block of text.
  734.  * buf is the buffer through which the text is both input and
  735.  * output. nchar is the size of the buffer. permp is a work
  736.  * buffer, and startn is the beginning of a sequence.
  737.  */
  738. crblock(permp, buf, nchar, startn)
  739. char *permp;
  740. char *buf;
  741. int nchar;
  742. long startn;
  743. {
  744.     register char *p1;
  745.     int n1;
  746.     int n2;
  747.     register char *t1, *t2, *t3;
  748.  
  749.     t1 = permp;
  750.     t2 = &permp[256];
  751.     t3 = &permp[512];
  752.  
  753.     n1 = startn&0377;
  754.     n2 = (startn>>8)&0377;
  755.     p1 = buf;
  756.     while(nchar--) {
  757.         *p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1;
  758.         n1++;
  759.         if(n1==256){
  760.             n1 = 0;
  761.             n2++;
  762.             if(n2==256) n2 = 0;
  763.         }
  764.         p1++;
  765.     }
  766. }
  767.  
  768. /*
  769.  * makekey: initialize buffers based on user key a.
  770.  */
  771. makekey(a, b)
  772. char *a, *b;
  773. {
  774.        register int i;
  775.     long t;
  776.     char temp[KSIZE + 1];
  777.  
  778.     for(i = 0; i < KSIZE; i++)
  779.         temp[i] = *a++;
  780.     time(&t);
  781.     t += getpid();
  782.     for(i = 0; i < 4; i++)
  783.         temp[i] ^= (t>>(8*i))&0377;
  784.     crinit(temp, b);
  785. }
  786.  
  787. /*
  788.  * crinit: besides initializing the encryption machine, this routine
  789.  * returns 0 if the key is null, and 1 if it is non-null.
  790.  */
  791. crinit(keyp, permp)
  792. char    *keyp, *permp;
  793. {
  794.        register char *t1, *t2, *t3;
  795.     register i;
  796.     int ic, k, temp;
  797.     unsigned random;
  798.     char buf[13];
  799.     long seed;
  800.  
  801.     t1 = permp;
  802.     t2 = &permp[256];
  803.     t3 = &permp[512];
  804.     if(*keyp == 0)
  805.         return(0);
  806.     strncpy(buf, keyp, 8);
  807.     while (*keyp)
  808.         *keyp++ = '\0';
  809.  
  810.     buf[8] = buf[0];
  811.     buf[9] = buf[1];
  812.     domakekey(buf);
  813.  
  814.     seed = 123;
  815.     for (i=0; i<13; i++)
  816.         seed = seed*buf[i] + i;
  817.     for(i=0;i<256;i++){
  818.         t1[i] = i;
  819.         t3[i] = 0;
  820.     }
  821.     for(i=0; i<256; i++) {
  822.         seed = 5*seed + buf[i%13];
  823.         random = seed % 65521;
  824.         k = 256-1 - i;
  825.         ic = (random&0377) % (k+1);
  826.         random >>= 8;
  827.         temp = t1[k];
  828.         t1[k] = t1[ic];
  829.         t1[ic] = temp;
  830.         if(t3[k]!=0) continue;
  831.         ic = (random&0377) % k;
  832.         while(t3[ic]!=0) ic = (ic+1) % k;
  833.         t3[k] = ic;
  834.         t3[ic] = k;
  835.     }
  836.     for(i=0; i<256; i++)
  837.         t2[t1[i]&0377] = i;
  838.     return(1);
  839. }
  840.  
  841. /*
  842.  * domakekey: the following is the major nonportable part of the encryption
  843.  * mechanism. A 10 character key is supplied in buffer.
  844.  * This string is fed to makekey (an external program) which
  845.  * responds with a 13 character result. This result is placed
  846.  * in buffer.
  847.  */
  848. domakekey(buffer)
  849. char *buffer;
  850. {
  851.        int pf[2];
  852.  
  853.     if (pipe(pf)<0)
  854.         pf[0] = pf[1] = -1;
  855.     if (fork()==0) {
  856.         close(0);
  857.         close(1);
  858.         dup(pf[0]);
  859.         dup(pf[1]);
  860.         execl("/usr/lib/makekey", "-", 0);
  861.         execl("/lib/makekey", "-", 0);
  862.         ex_exit(1);
  863.     }
  864.     write(pf[1], buffer, 10);
  865.     if (wait((int *)NULL)==-1 || read(pf[0], buffer, 13)!=13)
  866.         error("crypt: cannot generate key");
  867.     close(pf[0]);
  868.     close(pf[1]);
  869.     /* end of nonportable part */
  870. }
  871. #endif
  872.